package ua.com.alus.resvac.crm.stripes.action.resume;

import net.sourceforge.stripes.action.DefaultHandler;
import net.sourceforge.stripes.action.DontValidate;
import net.sourceforge.stripes.action.ForwardResolution;
import net.sourceforge.stripes.action.Resolution;
import net.sourceforge.stripes.action.UrlBinding;
import net.sourceforge.stripes.integration.spring.SpringBean;
import net.sourceforge.stripes.validation.EnumeratedTypeConverter;
import net.sourceforge.stripes.validation.LocalizableError;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import net.sourceforge.stripes.validation.ValidationErrors;
import net.sourceforge.stripes.validation.ValidationMethod;
import org.apache.commons.io.IOUtils;
import org.apache.log4j.Logger;
import ua.com.alus.resvac.crm.domen.entities.City;
import ua.com.alus.resvac.crm.domen.entities.Resume;
import ua.com.alus.resvac.crm.domen.entities.ResumeFile;
import ua.com.alus.resvac.crm.services.spring.AccountService;
import ua.com.alus.resvac.crm.services.spring.BaseService;
import ua.com.alus.resvac.crm.services.spring.ResumeService;
import ua.com.alus.resvac.crm.stripes.base.BaseAction;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;

/**
 * Create resume action
 * <p/>
 * Created by Usatov Alexey
 */

@UrlBinding("/resume/Resume.action")
public class ResumeAction extends BaseAction {
    private static final Logger LOGGER = Logger.getLogger(ResumeAction.class);

    public static final String RESUME_UUID_PARAM = "resumeUuid";
    public static final String RESUME_FILE_UUID_PARAM = "resumeFileUuid";
    public static final String CURRENT_CITY_ATTR = "currentCity";

    @SpringBean("/account/accountService")
    private AccountService accountService;

    @SpringBean("/resume/resumeService")
    private ResumeService resumeService;

    @SpringBean("/base/baseService")
    private BaseService baseService;

    @ValidateNestedProperties({
            @Validate(field = "phone", mask = "[\\+][0-9][0-9]+", required = false),
            @Validate(field = "year", required = true),
            @Validate(field = "sex", converter = EnumeratedTypeConverter.class, required = false),
            @Validate(field = "position", required = true),
            @Validate(field = "citizenship", converter = EnumeratedTypeConverter.class, required = true),
            @Validate(field = "fkProfAreaUuid", required = true),
            @Validate(field = "fkCityId", required = true),
            @Validate(field = "fkRegionId", required = true)
    })
    private Resume resume;


    private List<Resume> allResumes;

    private ResumeFile resumeFile;

    private List<String> resumeFilesUuid;

    /**
     * This only for displaying the name of city on form. Stripes after validation just make city object equals null
     */
    @SuppressWarnings("unchecked")
    public City getCurrentCity() {
        if (resume.getFkCityId() != null) {
            return baseService.getCityByUuid(resume.getFkCityId());
        }
        return null;
    }


    public Resume getResume() {
        return resume;
    }

    public void setResume(Resume resume) {
        this.resume = resume;
    }

    public ResumeFile getResumeFile() {
        return resumeFile;
    }

    public void setResumeFile(ResumeFile resumeFile) {
        this.resumeFile = resumeFile;
    }

    public List<Resume> getAllResumes() {
        return allResumes;
    }

    public void setAllResumes(List<Resume> allResumes) {
        this.allResumes = allResumes;
    }

    public List<String> getResumeFilesUuid() {
        return resumeFilesUuid;
    }

    public void setResumeFilesUuid(List<String> resumeFilesUuid) {
        this.resumeFilesUuid = resumeFilesUuid;
    }

    /**
     * Default handler for this action. Checks if user is logged in.
     *
     * @return resolution: if user is not logged in we send him to login form
     *         else to create resume view
     */
    @DefaultHandler
    @DontValidate
    public Resolution createResume() {
        initResumeByUUID();
        if (resume != null) {
            getContext().getRequest().setAttribute(CURRENT_CITY_ATTR, resume.getCity());
            updateCities();
        }
        return new ForwardResolution("/public/secured/createresume.jsp");

    }

    private boolean isAnonymous() {
        return accountService.getUserName() == null;
    }

    private void initResumeByUUID() {
        String resumeUuid;
        if ((resumeUuid = getContext().getRequest().getParameter(RESUME_UUID_PARAM)) != null) {
            resume = getResumeService().getResume(resumeUuid);
        }
        if (resume != null) {
            resumeFilesUuid = getResumeService().getResumeFilesUuid(resume.getUuid());
        }
    }

    @DontValidate
    public Resolution listResumes() {
        if (!isAnonymous()) {
            allResumes = resumeService.getResumes(accountService.getAccount(accountService.getUserName()).getUuid());
        }
        return new ForwardResolution("/public/secured/listResumes.jsp");
    }

    /**
     * Save resume handler
     *
     * @return Resolution - back to index.jsp page for now.
     */
    public Resolution saveResume() {
        //if uuid == null then we create resume else we update existing one
        resume.setAccount(accountService.getAccount(accountService.getUserName()));
        if (resume.getUuid() == null) {
            resume.setUuid(UUID.randomUUID().toString());
        }
        constructEntityFile(resume);
        resumeService.saveResume(resume);
        return listResumes();
    }

    @DontValidate
    public Resolution deleteResumeFile() {
        String resumeFileUuid;
        if ((resumeFileUuid = getContext().getRequest().getParameter(RESUME_FILE_UUID_PARAM)) != null) {
            getResumeService().deleteResumeFile(resumeFileUuid);
        }
        initResumeByUUID();
        updateCities();
        return new ForwardResolution("/public/secured/createresume.jsp");
    }

    /**
     * Handler for the uploading and constructing file for resume.
     *
     * @param resume Resume to which it belongs
     */
    private void constructEntityFile(Resume resume) {
        if (resumeFile != null && resumeFile.getFileBean() != null) {
            try {
                resumeFile.setFile(IOUtils.toByteArray(resumeFile.getFileBean().getInputStream()));
                resumeFile.getFileBean().delete();
                resumeFile.setUuid(UUID.randomUUID().toString());
                resume.setResumeFiles(Arrays.asList(resumeFile));
            } catch (IOException e) {
                LOGGER.error(e);
            }
        }
    }

    /**
     * Method for any validations on action "saveResume"
     *
     * @param validationErrors if any errors
     */
    @ValidationMethod(on = "saveResume")
    public void checkInputs(ValidationErrors validationErrors) {
        if (resume.getYear() == null) {
            validationErrors.add("resume.birthday", new LocalizableError("validation.required.valueNotPresent"));
        }
    }

    public ResumeService getResumeService() {
        return resumeService;
    }

    public BaseService getBaseService() {
        return baseService;
    }

    private List<City> cities;

    public List<City> getCities() {
        return cities;
    }

    @DontValidate
    public Resolution updateCities() {
        cities = getBaseService().getCities(resume.getFkRegionId());
        return new ForwardResolution("/public/secured/citiesFragment.jsp");
    }
}
